package com.ysd.lis.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.ysd.common.Result;
import com.ysd.lis.dto.SysMenuRoleDto;
import com.ysd.lis.dto.SysPointsRoleDto;
import com.ysd.lis.entity.*;
import com.ysd.lis.mapper.sys.*;
import com.ysd.lis.request.AuthFindUserListParam;
import com.ysd.lis.request.HandelUserAuthParam;
import com.ysd.lis.request.UserAuthAddParam;
import com.ysd.lis.service.SysUserAuthdetailService;
import com.ysd.lis.service.SysUserRoleService;
import com.ysd.util.SplitListUtils;
import com.ysd.util.ToolsUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;

/**
 * @program: server_lis
 * @author: liuQi
 * @create: 2023-10-28 17:25
 */
@Service
@Slf4j
public class SysUserAuthdetailServiceImpl extends ServiceImpl<SysUserAuthdetailMapper, SysUserAuthdetail> implements SysUserAuthdetailService {

    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SysModuleMapper sysModuleMapper;
    @Autowired
    private SysMenuMapper sysMenuMapper;
    @Autowired
    private SysPointsMapper sysPointsMapper;
    @Autowired
    private SysUserAuthdetailMapper sysUserAuthdetailMapper;
    @Autowired
    private SysRoleMapper sysRoleMapper;
    @Autowired
    private SysUserServiceImpl sysUserService;
    @Autowired
    private SysModuleServiceImpl sysModuleService;
    @Autowired
    private SysMenuServiceImpl sysMenuService;
    @Autowired
    private SysPointsServiceImpl sysPointsService;
    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;
    @Autowired
    private PubEmployeeServiceImpl pubEmployeeService;
    @Autowired
    private SysUserRoleService sysUserRoleService;
    @Autowired
    public SysModeUrlMapper sysModeUrlMapper;
    @Autowired
    private SysUserAuthdifferMapper sysUserAuthdifferMapper;
    @Autowired
    private SysUserRptGroupMapper sysUserRptGroupMapper;
    @Autowired
    private SysUserInstrSetupMapper sysUserInstrSetupMapper;

    /**
     * 根据角色ids获取用户详细信息Map
     *
     * @return
     */
    @Override
    public Result getSysUserAuthdetailsByRoleIds(HandelUserAuthParam handelUserAuthParam) {
        Map<String, Object> userAuthdetailsMap = geSysUserAuthMapByDetails(handelUserAuthParam.getUserId(), handelUserAuthParam.getRoleId(), "0");
        return Result.succ(1, "查询成功", userAuthdetailsMap);
    }

    @Override
    public Result getUserListByRoleId(AuthFindUserListParam authFindUserListParam) {
        MPJLambdaWrapper<SysUser> lambdaQueryWrapper = new MPJLambdaWrapper();
        lambdaQueryWrapper.selectAll(SysUser.class).selectAs(SysOrganization::getName, SysUser::getOrgName).selectAs(SysOrgDepartment::getName, SysUser::getDeptName).selectAs(SysOrgDepartment::getId, SysUser::getDeptId).leftJoin(SysUserRole.class, SysUserRole::getUserId, SysUser::getId).leftJoin(SysOrganization.class, SysOrganization::getId, SysUser::getOrgId).leftJoin(SysUserDept.class, SysUserDept::getUserId, SysUser::getId).leftJoin(SysOrgDepartment.class, SysOrgDepartment::getId, SysUserDept::getDeptId).eq(SysUserRole::getRoleId, authFindUserListParam.getRoleId());
        if (StringUtils.isNotBlank(authFindUserListParam.getKeywords())) {
            lambdaQueryWrapper.and(wrapper -> wrapper.like(SysUser::getUsername, authFindUserListParam.getKeywords()).or().like(SysUser::getRealname, authFindUserListParam.getKeywords()));
        }
        List<SysUser> userList = sysUserMapper.selectList(lambdaQueryWrapper);
        if (CollectionUtils.isNotEmpty(userList)) {
            List<String> userIds = userList.stream().map(SysUser::getId).collect(Collectors.toList());
            LambdaQueryWrapper<SysUserRole> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.in(SysUserRole::getUserId, userIds).eq(SysUserRole::getDelFlag, 0);
            List<SysUserRole> userRoleList = sysUserRoleMapper.selectList(queryWrapper);

            LambdaQueryWrapper<SysUserAuthdiffer> LambdaQueryWrapper1 = new LambdaQueryWrapper<>();
            LambdaQueryWrapper1.in(SysUserAuthdiffer::getUserId, userIds);
            List<SysUserAuthdiffer> sysUserAuthdiffers = sysUserAuthdifferMapper.selectList(LambdaQueryWrapper1);
            Map<String, List<SysUserAuthdiffer>> diffMap = sysUserAuthdiffers.stream().collect(Collectors.groupingBy(SysUserAuthdiffer::getUserId));
            for (SysUser user : userList) {
                List<SysUserRole> collect = userRoleList.stream().filter(ur -> ur.getUserId().equals(user.getId())).collect(Collectors.toList());
                List<String> roleIds = collect.stream().map(SysUserRole::getRoleId).collect(Collectors.toList());
                if (diffMap.containsKey(user.getId())) {
                    user.setDiffer(diffMap.get(user.getId()).size());
                } else {
                    user.setDiffer(0);
                }
                user.setRoleIds(roleIds);
            }
        }

        return Result.succ(1, "查询成功", userList);
    }

    @Override
    public Result getLoginUserAuthMapByUserId(String userId) {
        Map<String, Object> userAuthMapByDetails = geSysUserAuthMapByDetails(userId);
        return Result.succ(1, "查询成功", userAuthMapByDetails);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result handleUserAuthDetails(HandelUserAuthParam handelUserAuthParam) {
        // 先删除相详细数据
        deleteSysUserAuthdetailsByUserId(handelUserAuthParam.getUserId(), handelUserAuthParam.getRoleIds());
        // 再删除差异表数据
        deleteSysUserAuthDifferByUserId(handelUserAuthParam.getUserId(), handelUserAuthParam.getRoleIds());
        // 再插入详细数据
        saveSysUserAuthdetail(handelUserAuthParam.getUserId(), handelUserAuthParam.getRoleIds());
        // 最后查询数据
        return getSysUserAuthdetailsByRoleIds(handelUserAuthParam);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result deleteUserAuthById(String id) {
        SysUserAuthdetail sysUserAuthdetail = sysUserAuthdetailMapper.selectById(id);
        SysUserAuthdiffer sysUserAuthdiffer = new SysUserAuthdiffer();
        BeanUtil.copyProperties(sysUserAuthdetail, sysUserAuthdiffer);
        int insert = sysUserAuthdifferMapper.insert(sysUserAuthdiffer);
        int i = sysUserAuthdetailMapper.deleteById(id);
        if (i > 0) {
            return Result.succ(1, "删除成功", 1);
        } else {
            return Result.fail("查询失败！");
        }
    }

    public void addUserAfterDetails(SysUser sysUser, List<String> roleIds) {
        List<SysUser> list = new ArrayList<>();
        list.add(sysUser);
        List<SysUserAuthdetail> sysUserAuthdetails = buildSysUserAuthDetails(list, roleIds.get(0));
        this.saveBatch(sysUserAuthdetails);
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result addUserAuthDetails(UserAuthAddParam userAuthAddParam) {
        // 查询用户详细信息
        SysUser SysUser = sysUserMapper.selectById(userAuthAddParam.getUserId());
        List<SysUserAuthdetail> sysUserAuthdetails = new ArrayList<>();
        // 查询菜单详细信息
        if (userAuthAddParam.getMenus().size() > 0) {
            MPJLambdaWrapper<SysMenu> lambdaQueryWrapper = new MPJLambdaWrapper();
            lambdaQueryWrapper.selectAll(SysMenu.class).selectAs(SysModule::getName, SysMenuRoleDto::getModuleName).selectAs(SysModule::getCode, SysMenuRoleDto::getModuleCode).leftJoin(SysModule.class, SysModule::getId, SysMenu::getModuleId).eq(SysMenu::getDelFlag, "0").in(SysMenu::getId, userAuthAddParam.getMenus());
            List<SysMenuRoleDto> sysMenuRoleDtos = sysMenuMapper.selectJoinList(SysMenuRoleDto.class, lambdaQueryWrapper);
            // 如果详情表中没有一级菜单则 添加二级菜单时同时插入二级菜单的父级
            List<String> parentIds = sysMenuRoleDtos.stream().map(SysMenuRoleDto::getParentId).collect(Collectors.toList());
            LambdaQueryWrapper<SysMenu> lambdaQueryWrapper1 = new LambdaQueryWrapper();
            lambdaQueryWrapper1.in(SysMenu::getId, parentIds);
            List<SysMenu> sysMenus = sysMenuMapper.selectList(lambdaQueryWrapper1);
            // 查询当前用户下是否有此父级菜单
            LambdaQueryWrapper<SysUserAuthdetail> lambdaQueryWrapper2 = new LambdaQueryWrapper();
            lambdaQueryWrapper2.eq(SysUserAuthdetail::getUserId, userAuthAddParam.getUserId()).in(SysUserAuthdetail::getFunctionId, parentIds);
            List<SysUserAuthdetail> sysUserAuthdetails1 = sysUserAuthdetailMapper.selectList(lambdaQueryWrapper2);
            List<String> collected = sysUserAuthdetails1.stream().map(SysUserAuthdetail::getFunctionId).collect(Collectors.toList());
            sysMenus.stream().filter(item -> !collected.contains(item.getId())).forEach(item -> {
                SysMenuRoleDto sysMenuRoleDto = new SysMenuRoleDto();
                BeanUtil.copyProperties(item, sysMenuRoleDto);
                sysMenuRoleDtos.add(sysMenuRoleDto);
            });
            sysUserAuthdetails.addAll(getSysUserAuthdetailByMenu(SysUser, sysMenuRoleDtos, "0"));
        }
        // 查询功能详细信息
        if (userAuthAddParam.getPoints().size() > 0) {
            MPJLambdaWrapper<SysPoints> lambdaQueryWrapper1 = new MPJLambdaWrapper();
            lambdaQueryWrapper1.selectAll(SysPoints.class).selectAs(SysModule::getName, SysMenuRoleDto::getModuleName).selectAs(SysModule::getCode, SysMenuRoleDto::getModuleCode).leftJoin(SysModule.class, SysModule::getId, SysPoints::getModuleId).eq(SysPoints::getDelFlag, "0").in(SysPoints::getId, userAuthAddParam.getPoints());
            List<SysMenuRoleDto> sysPoints = sysPointsMapper.selectJoinList(SysMenuRoleDto.class, lambdaQueryWrapper1);
            List<SysUserAuthdetail> sysUserAuthdetailByMenu1 = getSysUserAuthdetailByMenu(SysUser, sysPoints, "1");
            sysUserAuthdetails.addAll(sysUserAuthdetailByMenu1);
        }
        List<SysUserAuthdetail> resultAuthdetails = new ArrayList<>();
        if (StringUtils.isNotBlank(userAuthAddParam.getRoleId())) {
            resultAuthdetails = sysUserAuthdetails.stream().map(item -> {
                item.setRoleId(userAuthAddParam.getRoleId());
                item.setRoleName(userAuthAddParam.getRoleName());
                return item;
            }).collect(Collectors.toList());
        }
        boolean b = this.saveBatch(resultAuthdetails);
        // 删除差异表数据
        List<String> collected = resultAuthdetails.stream().map(SysUserAuthdetail::getFunctionId).collect(Collectors.toList());
        LambdaQueryWrapper<SysUserAuthdiffer> lambdaQueryWrapper = new LambdaQueryWrapper();
        lambdaQueryWrapper.eq(SysUserAuthdiffer::getUserId, userAuthAddParam.getUserId()).in(SysUserAuthdiffer::getFunctionId, collected);
        int delete = sysUserAuthdifferMapper.delete(lambdaQueryWrapper);
        return Result.succ(1, "添加成功", b);
    }

    @Override
    public Result getDifferenceSetRoles(HandelUserAuthParam handelUserAuthParam) {
        String userId = handelUserAuthParam.getUserId();
        List<String> roleIds = handelUserAuthParam.getRoleIds();
        Map<String, Object> resultMap = new HashMap<>();
        Map<String, Object> userAuthMapByDetails = geSysUserAuthMapByDetails(userId, null, "1");
        List<SysModule> byDetailsModules = (List<SysModule>) userAuthMapByDetails.get("modules");
        Map<String, List<SysMenu>> byDetailsModuleMenuMap = (Map<String, List<SysMenu>>) userAuthMapByDetails.get("moduleMenuMap");
        Map<String, List<SysPoints>> byDetailsModulePointCodeMap = (Map<String, List<SysPoints>>) userAuthMapByDetails.get("modulePointCodeMap");
        Map<String, Object> userAuthMapByRoles = geSysUserAuthMapByRoles(userId, roleIds);
        Map<String, List<SysMenu>> byRolesModuleMenuMap = (Map<String, List<SysMenu>>) userAuthMapByRoles.get("moduleMenuMap");
        Map<String, List<SysPoints>> byRolesModulePointCodeMap = (Map<String, List<SysPoints>>) userAuthMapByRoles.get("modulePointCodeMap");
        // 先判断map中是否有模块信息
        Map<String, List<SysMenu>> moduleMenuMap = new HashMap<>();
        // 求菜单差集
        byRolesModuleMenuMap.forEach((key, value) -> {
            if (byDetailsModuleMenuMap.containsKey(key)) {
                List<SysMenu> detailsMenus = byDetailsModuleMenuMap.get(key);
                List<String> collected = detailsMenus.stream().filter(e -> StringUtils.isNotBlank(e.getParentId())).map(e -> e.getId()).collect(Collectors.toList());
                List<SysMenu> SysMenuStream = value.stream().filter(item -> !collected.contains(item.getId())).collect(Collectors.toList());

                List<SysMenu> returnList = new ArrayList<>();
                SysMenuStream.stream().forEach(SysMenu -> {
                    if (StringUtils.isBlank(SysMenu.getParentId())) {
                        SysMenu.setChildren(getChildren(SysMenu, SysMenuStream));
                        returnList.add(SysMenu);
                    }
                });
                if (returnList.size() != 0) {
                    moduleMenuMap.put(key, returnList);
                }
            } else {
                List<SysMenu> returnList = new ArrayList<>();
                value.stream().forEach(SysMenu -> {
                    if (StringUtils.isBlank(SysMenu.getParentId())) {
                        SysMenu.setChildren(getChildren(SysMenu, value));
                        returnList.add(SysMenu);
                    }
                });
                if (returnList.size() != 0) {
                    moduleMenuMap.put(key, returnList);
                }
            }
        });
        resultMap.put("moduleMenuMap", moduleMenuMap);
        // 求功能差集
        Map<String, List<SysPoints>> modulePointCodeMap = new HashMap<>();
        byRolesModulePointCodeMap.forEach((key, value) -> {
            if (byDetailsModulePointCodeMap.containsKey(key)) {
                List<SysPoints> detailsPoints = byDetailsModulePointCodeMap.get(key);
                List<SysPoints> points = value.stream().filter(item -> !detailsPoints.stream().map(e -> e.getId()).collect(Collectors.toList()).contains(item.getId())).collect(Collectors.toList());
                if (points.size() != 0) {
                    modulePointCodeMap.put(key, points);
                }
            }
        });
        resultMap.put("modulePointCodeMap", modulePointCodeMap);
        List<SysModule> collect = byDetailsModules.stream().filter(item -> moduleMenuMap.containsKey(item.getId()) || modulePointCodeMap.containsKey(item.getId())).collect(Collectors.toList());
        resultMap.put("modules", collect);
        return Result.succ(1, "查询成功", resultMap);
    }

    public Map<String, Object> geSysUserAuthMapByDetails(String userId, String roleId, String findType) {
        // 构建返回集合
        Map<String, Object> resultMap = new HashMap<>();
        MPJLambdaWrapper<SysUserAuthdetail> modelsByRoleIdsWrapper = new MPJLambdaWrapper<>();
        modelsByRoleIdsWrapper.selectAll(SysUserAuthdetail.class).eq(SysUserAuthdetail::getUserId, userId);
        if (StringUtils.isNotBlank(roleId)) {
            modelsByRoleIdsWrapper.eq(SysUserAuthdetail::getRoleId, roleId);
        }
        List<SysUserAuthdetail> sysUserAuthdetails = sysUserAuthdetailMapper.selectList(modelsByRoleIdsWrapper);
        // 获取模块数据
        List<SysModule> sysModules = sysUserAuthdetails.stream().filter(sysUserAuthdetail -> ObjectUtil.isNotEmpty(sysUserAuthdetail) && StrUtil.isNotEmpty(sysUserAuthdetail.getModuleId()) && StrUtil.isNotEmpty(sysUserAuthdetail.getModuleName())).map(sysUserAuthdetail -> {

//            List<SysModule> sysModules = sysUserAuthdetails.stream().map(sysUserAuthdetail -> {
            SysModule sysModule = new SysModule();
            sysModule.setId(sysUserAuthdetail.getModuleId());
            sysModule.setName(sysUserAuthdetail.getModuleName());
            return sysModule;
        }).collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(sysModule -> sysModule.getId()))), ArrayList::new));
        resultMap.put("modules", sysModules);

        // 获取模块菜单数据
        MPJLambdaWrapper<SysUserAuthdetail> menuByRoleIdsWrapper = new MPJLambdaWrapper<>();
        menuByRoleIdsWrapper.select(SysMenu::getId, SysMenu::getTitle, SysMenu::getParentId, SysMenu::getIcon, SysMenu::getUrl, SysMenu::getModuleId, SysMenu::getIsTool, SysMenu::getCode, SysMenu::getOpenWith).selectAs(SysUserAuthdetail::getId, SysMenu::getCreator).leftJoin(SysMenu.class, SysMenu::getId, SysUserAuthdetail::getFunctionId).eq(SysUserAuthdetail::getAuthType, "0").eq(SysUserAuthdetail::getUserId, userId);
        List<SysMenu> SysMenus = sysUserAuthdetailMapper.selectJoinList(SysMenu.class, menuByRoleIdsWrapper);
        if ("0".equals(findType)) {
            List<SysMenu> returnList = new ArrayList<>();
            SysMenus.stream().forEach(SysMenu -> {
                if (StringUtils.isBlank(SysMenu.getParentId())) {
                    SysMenu.setChildren(getChildren(SysMenu, SysMenus));
                    returnList.add(SysMenu);
                }
            });
            Map<String, List<SysMenu>> moduleMenuMap = returnList.stream().collect(Collectors.groupingBy(SysMenu::getModuleId));
            resultMap.put("moduleMenuMap", moduleMenuMap);
        } else {
            Map<String, List<SysMenu>> moduleMenuMap = SysMenus.stream().collect(Collectors.groupingBy(SysMenu::getModuleId));
            resultMap.put("moduleMenuMap", moduleMenuMap);
        }


        // 获取模块功能数据
        Map<String, List<SysPoints>> modulePointMap = sysUserAuthdetails.stream().filter(item -> "1".equals(item.getAuthType())).map(sysUserAuthdetail -> {
            SysPoints sysPoints = new SysPoints();
            // 借用sysPoints的Creator字段存储详情id
            sysPoints.setCreator(sysUserAuthdetail.getId());
            sysPoints.setId(sysUserAuthdetail.getFunctionId());
            sysPoints.setTitle(sysUserAuthdetail.getFunctionName());
            sysPoints.setModuleId(sysUserAuthdetail.getModuleId());
            return sysPoints;
        }).collect(Collectors.groupingBy(SysPoints::getModuleId));
        resultMap.put("modulePointCodeMap", modulePointMap);
        return resultMap;
    }

    public Map<String, Object> geSysUserAuthMapByDetails(String userId) {
        // 构建返回集合
        Map<String, Object> resultMap = new HashMap<>();
        MPJLambdaWrapper<SysUserAuthdetail> modelsByRoleIdsWrapper = new MPJLambdaWrapper<>();
        modelsByRoleIdsWrapper.distinct()
                .select(SysModule::getId, SysModule::getName, SysModule::getBaseUrl, SysModule::getBigIconBgcolour, SysModule::getIcon, SysModule::getSn, SysModule::getCode, SysModule::getBaseModule)
                .leftJoin(SysModule.class, SysModule::getId, SysUserAuthdetail::getModuleId)
                .eq(SysModule::getDelFlag, 0)
                .eq(SysUserAuthdetail::getUserId, userId);
        modelsByRoleIdsWrapper.orderByAsc(SysModule::getSn);
        List<SysModule> sysModules = sysUserAuthdetailMapper.selectJoinList(SysModule.class, modelsByRoleIdsWrapper);

        //sysModules = sysModules.stream().sorted(Comparator.nullsLast(Comparator.comparing(SysModule::getSn))).collect(Collectors.toList());
        // 获取模块数据
        resultMap.put("modules", sysModules);

        // 获取模块菜单数据
        MPJLambdaWrapper<SysUserAuthdetail> menuByRoleIdsWrapper = new MPJLambdaWrapper<>();
        menuByRoleIdsWrapper.select(SysMenu::getId, SysMenu::getTitle, SysMenu::getParentId, SysMenu::getIcon, SysMenu::getUrl, SysMenu::getModuleId, SysMenu::getIsTool, SysMenu::getIsAssembly, SysMenu::getIsDictMenu, SysMenu::getCode, SysMenu::getOpenWith, SysMenu::getSn)
                .leftJoin(SysMenu.class, SysMenu::getId, SysUserAuthdetail::getFunctionId)
                .eq(SysUserAuthdetail::getAuthType, "0")
                .eq(SysUserAuthdetail::getUserId, userId)
                .eq(SysMenu::getDelFlag, 0)
                .orderByAsc(SysMenu::getSn);
        List<SysMenu> SysMenus = sysUserAuthdetailMapper.selectJoinList(SysMenu.class, menuByRoleIdsWrapper);
        for(SysMenu sysMenu:SysMenus){
            if(ToolsUtils.isNotEmpty(sysMenu.getParentId())){
                Integer sn = sysMenu.getSn();
                //sn用字符串代替 用三位，不够的用0补齐
                if(ToolsUtils.isNotEmpty(sn)){
                    sysMenu.setTitleSn(String.format("%3s", sn).replace(' ', '0'));
                }
            }
        }
        //获取当前登陆人下的所有角色
        MPJLambdaWrapper<SysRole> sysRoleWrapper = new MPJLambdaWrapper<>();
        sysRoleWrapper.selectAll(SysRole.class)
                .innerJoin(SysUserRole.class,p-> p.eq(SysUserRole::getRoleId,SysRole::getId).eq(SysUserRole::getDelFlag,0))
                .innerJoin(SysUser.class,p->p.eq(SysUser::getId,SysUserRole::getUserId).eq(SysUser::getId,userId).eq(SysUser::getDelFlag,0))
                .eq(SysRole::getDelFlag,0);
        List<SysRole> sysRoles = sysRoleMapper.selectList(sysRoleWrapper);
        resultMap.put("sysRoles", sysRoles);
        // 获取模式路径
        SysUser SysUser = sysUserMapper.selectById(userId);
        LambdaQueryWrapper<SysModeUrl> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SysModeUrl::getDelFlag, 0);
        lambdaQueryWrapper.eq(SysModeUrl::getModeCode, StringUtils.isNotBlank(SysUser.getUserMode()) ? SysUser.getUserMode() : "0");
        List<SysModeUrl> sysModeUrls = sysModeUrlMapper.selectList(lambdaQueryWrapper);
        // ToDo 业务逻辑优化
        Map<String, String> ModeUrlmap = sysModeUrls.stream().collect(Collectors.toMap(SysModeUrl::getMenuId, SysModeUrl::getModeUrl, (k1, k2) -> k1));

        List<SysMenu> returnList = new ArrayList<>();
        SysMenus.stream().map(item -> {
            if (ModeUrlmap.containsKey(item.getId())) {
                item.setUrl(ModeUrlmap.get(item.getId()));
            }
            return item;
        }).forEach(SysMenu -> {
            if (StringUtils.isBlank(SysMenu.getParentId())) {
                SysMenu.setChildren(getChildren(SysMenu, SysMenus));
                returnList.add(SysMenu);
            }
        });
        Map<String, List<SysMenu>> moduleMenuMap = returnList.stream().collect(Collectors.groupingBy(SysMenu::getModuleId));
        resultMap.put("moduleMenuMap", moduleMenuMap);

        // 获取模块菜单数据
        MPJLambdaWrapper<SysUserAuthdetail> pointsByRoleIdsWrapper = new MPJLambdaWrapper<>();
        pointsByRoleIdsWrapper.select(SysPoints::getCode, SysPoints::getModuleId).leftJoin(SysPoints.class, SysPoints::getId, SysUserAuthdetail::getFunctionId).eq(SysUserAuthdetail::getAuthType, "1").eq(SysUserAuthdetail::getUserId, userId);
        List<SysPoints> sysPoints = sysUserAuthdetailMapper.selectJoinList(SysPoints.class, pointsByRoleIdsWrapper);
        Map<String, List<SysPoints>> modulePointMap = sysPoints.stream().collect(Collectors.groupingBy(SysPoints::getModuleId));

        Map<String, List<String>> modulePointCodeMap = new HashMap<>();
        modulePointMap.forEach((key, value) -> {
            List<String> collect = value.stream().map(SysPoints::getCode).collect(Collectors.toList());
            modulePointCodeMap.put(key, collect);
        });
        resultMap.put("modulePointCodeMap", modulePointCodeMap);

        // 获取报告单元数据
        LambdaQueryWrapper<SysUserRptGroup> lambdaQueryWrapper1 = new LambdaQueryWrapper<>();
        lambdaQueryWrapper1.eq(SysUserRptGroup::getUserId, SysUser.getId());
        List<SysUserRptGroup> sysUserRptGroups = sysUserRptGroupMapper.selectList(lambdaQueryWrapper1);
        List<String> collected = sysUserRptGroups.stream().distinct().map(item -> item.getRptGroupId()).collect(Collectors.toList());
        resultMap.put("rptGroupList", collected);

        // 获取仪器
        LambdaQueryWrapper<SysUserInstrSetup> lambdaWrapper2 = new LambdaQueryWrapper<>();
        lambdaWrapper2.eq(SysUserInstrSetup::getUserId, SysUser.getId());
        List<SysUserInstrSetup> sysUserInstrSetups = sysUserInstrSetupMapper.selectList(lambdaWrapper2);
        List<String> collected1 = sysUserInstrSetups.stream().distinct().map(item -> item.getInstrSetupId()).collect(Collectors.toList());
        resultMap.put("instrSetupList", collected1);
        return resultMap;
    }

    public Map<String, Object> geSysUserAuthMapByRoles(String userId, List<String> roleIds) {
        // 构建返回集合
        Map<String, Object> resultMap = new HashMap<>();
        if (roleIds.size() == 0) {
            return resultMap;
        } else {
            // 获取模块列表
            MPJLambdaWrapper<SysModule> modelsByRoleIdsWrapper = new MPJLambdaWrapper<>();
            modelsByRoleIdsWrapper.distinct().selectAll(SysModule.class).leftJoin(SysRoleModule.class, SysRoleModule::getModuleId, SysModule::getId).eq(SysModule::getDelFlag, "0").in(SysRoleModule::getRoleId, roleIds);

            List<SysModule> sysModules = sysModuleMapper.selectList(modelsByRoleIdsWrapper);
            resultMap.put("modules", sysModules);

            // 获取模块与菜单对象
            MPJLambdaWrapper<SysMenu> menusByRoleIdsWrapper = new MPJLambdaWrapper<>();
            menusByRoleIdsWrapper.distinct().selectAll(SysMenu.class).leftJoin(SysRoleMenu.class, SysRoleMenu::getMenuId, SysMenu::getId).eq(SysMenu::getDelFlag, '0').in(SysRoleMenu::getRoleId, roleIds);
            List<SysMenu> SysMenus = sysMenuMapper.selectList(menusByRoleIdsWrapper);

            Map<String, List<SysMenu>> moduleMenuMap = SysMenus.stream().collect(Collectors.groupingBy(SysMenu::getModuleId));
            resultMap.put("moduleMenuMap", moduleMenuMap);

            // 获取菜单功能点对象
            MPJLambdaWrapper<SysPoints> pointsListByRoleIdsWrapper = new MPJLambdaWrapper<>();
            pointsListByRoleIdsWrapper.distinct().selectAll(SysPoints.class).leftJoin(SysRolePoints.class, SysRolePoints::getPointsId, SysPoints::getId).eq(SysPoints::getDelFlag, "0").in(SysRolePoints::getRoleId, roleIds);
            List<SysPoints> sysPoints = sysPointsMapper.selectList(pointsListByRoleIdsWrapper);
            Map<String, List<SysPoints>> modulePointMap = sysPoints.stream().collect(Collectors.groupingBy(SysPoints::getModuleId));

            resultMap.put("modulePointCodeMap", modulePointMap);
            return resultMap;
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public Result deleteSysUserAuthdetailsByUserId(String userId, List<String> roleIds) {
        // 先删除用户详情表数据
        LambdaQueryWrapper<SysUserAuthdetail> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SysUserAuthdetail::getUserId, userId);
        int delete = sysUserAuthdetailMapper.delete(lambdaQueryWrapper);
        if (delete > 0) {
            return Result.succ(1, "删除成功！", delete);
        } else {
            return Result.succ(0, "删除失败！", delete);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public Result deleteSysUserAuthDifferByUserId(String userId, List<String> roleIds) {
        // 先删除用户详情表数据
        LambdaQueryWrapper<SysUserAuthdiffer> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SysUserAuthdiffer::getUserId, userId);
        int delete = sysUserAuthdifferMapper.delete(lambdaQueryWrapper);
        if (delete > 0) {
            return Result.succ(1, "删除成功！", delete);
        } else {
            return Result.succ(0, "删除失败！", delete);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void saveSysUserAuthdetail(String userId, List<String> roleIds) {
        SysUser SysUser = sysUserMapper.selectById(userId);

        // 获取模块map
        MPJLambdaWrapper<SysModule> modelsByRoleIdsWrapper = new MPJLambdaWrapper<>();
        modelsByRoleIdsWrapper.distinct().selectAll(SysModule.class).leftJoin(SysRoleModule.class, SysRoleModule::getModuleId, SysModule::getId).in(SysRoleModule::getRoleId, roleIds);
        List<SysModule> sysModules = sysModuleMapper.selectList(modelsByRoleIdsWrapper);
        Map<String, SysModule> collect = sysModules.stream().collect(Collectors.toMap(SysModule::getId, v -> v, (k1, k2) -> k1));
        List<SysUserAuthdetail> sysUserAuthdetails = new ArrayList<>();
        // 获取菜单数据
        MPJLambdaWrapper<SysMenu> menusByRoleIdsWrapper = new MPJLambdaWrapper<>();
        menusByRoleIdsWrapper.distinct().selectAll(SysMenu.class).selectAs(SysRole::getId, SysMenuRoleDto::getRoleId).selectAs(SysRole::getCode, SysMenuRoleDto::getRoleCode).selectAs(SysRole::getRoleName, SysMenuRoleDto::getRoleName).leftJoin(SysRoleMenu.class, SysRoleMenu::getMenuId, SysMenu::getId).leftJoin(SysRole.class, SysRole::getId, SysRoleMenu::getRoleId).in(SysRoleMenu::getRoleId, roleIds);
        List<SysMenuRoleDto> SysMenus = sysMenuMapper.selectJoinList(SysMenuRoleDto.class, menusByRoleIdsWrapper);
        // 添加菜单详细信息
        SysMenus.stream().forEach(SysMenu -> {
            SysModule sysModule = collect.get(SysMenu.getModuleId());
            if (ObjectUtil.isNotEmpty(sysModule)) {
                SysUserAuthdetail sysUserAuthdetail = new SysUserAuthdetail();
                sysUserAuthdetail.setUserId(SysUser.getId());
                sysUserAuthdetail.setUserName(SysUser.getRealname());
                sysUserAuthdetail.setUserCode(SysUser.getUsername());
                sysUserAuthdetail.setOrgId(SysUser.getOrgId());
                sysUserAuthdetail.setPassword(SysUser.getPassword());
                sysUserAuthdetail.setRoleId(SysMenu.getRoleId());
                sysUserAuthdetail.setRoleCode(SysMenu.getRoleCode());
                sysUserAuthdetail.setRoleName(SysMenu.getRoleName());
//                SysModule sysModule = collect.get(SysMenu.getModuleId());
//            if (ObjectUtil.isNotEmpty(sysModule)) {
                sysUserAuthdetail.setModuleId(sysModule.getId());
                sysUserAuthdetail.setModuleCode(sysModule.getCode());
                sysUserAuthdetail.setModuleName(sysModule.getName());
//            }
                sysUserAuthdetail.setFunctionId(SysMenu.getId());
                if (StringUtils.isBlank(SysMenu.getParentId())) {
                    sysUserAuthdetail.setMenuType("0");
                } else {
                    sysUserAuthdetail.setMenuType("1");
                }
                sysUserAuthdetail.setFunctionName(SysMenu.getTitle());
                sysUserAuthdetail.setAuthType("0");
                sysUserAuthdetails.add(sysUserAuthdetail);
            }
        });
        // 获取功能点数据
        MPJLambdaWrapper<SysPoints> pointsByRoleIdsWrapper = new MPJLambdaWrapper<>();
        pointsByRoleIdsWrapper.distinct().selectAll(SysPoints.class).selectAs(SysRole::getId, SysMenuRoleDto::getRoleId).selectAs(SysRole::getCode, SysMenuRoleDto::getRoleCode).selectAs(SysRole::getRoleName, SysMenuRoleDto::getRoleName).leftJoin(SysRolePoints.class, SysRolePoints::getPointsId, SysPoints::getId).leftJoin(SysRole.class, SysRole::getId, SysRolePoints::getRoleId).in(SysRolePoints::getRoleId, roleIds);
        List<SysPointsRoleDto> tPoints = sysPointsMapper.selectJoinList(SysPointsRoleDto.class, pointsByRoleIdsWrapper);
        // 添加功能点数据
        tPoints.stream().forEach(sysPoints -> {
            SysModule sysModule = collect.get(sysPoints.getModuleId());
            if (ObjectUtil.isNotEmpty(sysModule)) {
                SysUserAuthdetail sysUserAuthdetail = new SysUserAuthdetail();
                sysUserAuthdetail.setUserId(SysUser.getId());
                sysUserAuthdetail.setUserName(SysUser.getRealname());
                sysUserAuthdetail.setUserCode(SysUser.getUsername());
                sysUserAuthdetail.setOrgId(SysUser.getOrgId());
                sysUserAuthdetail.setPassword(SysUser.getPassword());
                sysUserAuthdetail.setRoleId(sysPoints.getRoleId());
                sysUserAuthdetail.setRoleCode(sysPoints.getRoleCode());
                sysUserAuthdetail.setRoleName(sysPoints.getRoleName());
//                SysModule sysModule = collect.get(sysPoints.getModuleId());
//            if (ObjectUtil.isNotEmpty(sysModule)) {
                sysUserAuthdetail.setModuleId(sysModule.getId());
                sysUserAuthdetail.setModuleCode(sysModule.getCode());
                sysUserAuthdetail.setModuleName(sysModule.getName());
//            }
                sysUserAuthdetail.setFunctionId(sysPoints.getId());
                sysUserAuthdetail.setFunctionName(sysPoints.getTitle());
                sysUserAuthdetail.setAuthType("1");
                sysUserAuthdetails.add(sysUserAuthdetail);
            }
        });
        List<SysUserAuthdetail> collect1 = sysUserAuthdetails.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(sysUserAuthdetail -> sysUserAuthdetail.getFunctionId()))), ArrayList::new));
//        boolean b = this.saveBatch(collect1);


        long startTime = System.currentTimeMillis();
        List<List<SysUserAuthdetail>> lists = SplitListUtils.pagingList(collect1, 10);
        CountDownLatch countDownLatch = new CountDownLatch(lists.size());
        for (List<SysUserAuthdetail> SysUserAuthdetails : lists) {
            this.executeAsync(SysUserAuthdetails, countDownLatch);
        }
        try {
            countDownLatch.await();
            long endTime = System.currentTimeMillis();
            log.info("一共耗时time: " + (endTime - startTime) / 1000 + " s");
        } catch (Exception e) {
            log.error("阻塞异常:" + e.getMessage());
        }
    }

    public List<SysUserAuthdetail> getSysUserAuthdetailByMenu(SysUser SysUser, List<SysMenuRoleDto> SysMenus, String authType) {
        List<SysUserAuthdetail> sysUserAuthdetails = new ArrayList<>();
        SysMenus.stream().forEach(SysMenu -> {
            SysUserAuthdetail sysUserAuthdetail = new SysUserAuthdetail();
            sysUserAuthdetail.setUserId(SysUser.getId());
            sysUserAuthdetail.setUserName(SysUser.getRealname());
            sysUserAuthdetail.setUserCode(SysUser.getUsername());
            sysUserAuthdetail.setOrgId(SysUser.getOrgId());
            sysUserAuthdetail.setPassword(SysUser.getPassword());
            sysUserAuthdetail.setRoleId(SysMenu.getRoleId());
            sysUserAuthdetail.setRoleCode(SysMenu.getRoleCode());
            sysUserAuthdetail.setRoleName(SysMenu.getRoleName());
            sysUserAuthdetail.setModuleId(SysMenu.getModuleId());
            sysUserAuthdetail.setModuleCode(SysMenu.getModuleCode());
            sysUserAuthdetail.setModuleName(SysMenu.getModuleName());
            sysUserAuthdetail.setFunctionId(SysMenu.getId());
            sysUserAuthdetail.setFunctionName(SysMenu.getTitle());
            if (authType.equals("0")) {
                if (StringUtils.isBlank(SysMenu.getParentId())) {
                    sysUserAuthdetail.setMenuType("0");
                } else {
                    sysUserAuthdetail.setMenuType("1");
                }
                sysUserAuthdetail.setAuthType("0");
            } else {
                sysUserAuthdetail.setAuthType("1");
            }
            sysUserAuthdetails.add(sysUserAuthdetail);
        });
        return sysUserAuthdetails;
    }

    public List<SysMenu> getChildren(SysMenu a, List<SysMenu> menuList) {
        List<SysMenu> result = new ArrayList();
        for (SysMenu menu : menuList) {
            if (StringUtils.isBlank(menu.getParentId())) {
                menu.setParentName("");
            }
            if (StringUtils.isNotBlank(menu.getParentId()) && menu.getParentId().equals(a.getId())) {
                menu.setParentName(a.getTitle());
                result.add(menu);
            }
        }
        for (SysMenu menu : result) {
            menu.setChildren(getChildren(menu, menuList));
        }
        if (result.size() == 0) {
            return new ArrayList<>();
        }
        return result;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result importSysUserAuthDetailsByEmployee(String roleId, List<String> employeeIds) {
        // 查询员工列表
        List<PubEmployee> employeeList = pubEmployeeService.findEmployeeListByIds(employeeIds);
        // 如果用户表中存在员工code过滤掉
        List<String> codeList = employeeList.stream().map(PubEmployee::getCode).collect(Collectors.toList());
        List<SysUser> sysUsers = new ArrayList<>();
        // 判断数据库有没有此人，有则查询出来直接分配角色
        MPJLambdaWrapper<SysUser> queryWrapper = new MPJLambdaWrapper<>();
        queryWrapper.selectAll(SysUser.class).eq(SysUser::getDelFlag, "0").in(SysUser::getHisEmployeeCode, codeList);
        List<SysUser> users = sysUserMapper.selectList(queryWrapper);
        if (users.size() > 0) {
            List<SysUserRole> sysUserRoles = sysUserService.buildBatchUserRoles(users, roleId);
            sysUserRoleService.saveBatch(sysUserRoles);
            sysUsers.addAll(users);
        }
        // 如果没有此人，则新增用户，并添加角色
        List<PubEmployee> collect1 = employeeList.stream().filter(em -> !users.stream().map(SysUser::getHisEmployeeCode).collect(Collectors.toList()).contains(em.getCode())).collect(Collectors.toList());
        sysUsers.addAll(sysUserService.importUsers(roleId, collect1, "1"));

        if (CollectionUtil.isEmpty(sysUsers) || sysUsers.isEmpty()) {
            return Result.fail("无员工数据导入！");
        }
        List<SysUserAuthdetail> sysUserAuthDetails = buildSysUserAuthDetails(sysUsers, roleId);
        long startTime = System.currentTimeMillis();
        List<List<SysUserAuthdetail>> lists = SplitListUtils.pagingList(sysUserAuthDetails, 500);
        CountDownLatch countDownLatch = new CountDownLatch(lists.size());
        for (List<SysUserAuthdetail> SysUserAuthdetails : lists) {
            this.executeAsync(SysUserAuthdetails, countDownLatch);
        }
        try {
            countDownLatch.await();
            long endTime = System.currentTimeMillis();
            log.info("一共耗时time: " + (endTime - startTime) / 1000 + " s");
        } catch (Exception e) {
            log.error("阻塞异常:" + e.getMessage());
        }
        return Result.succ(1, "导入成功", null);
    }

    @Async("asyncServiceExecutor")
    public void executeAsync(List<SysUserAuthdetail> SysUserAuthdetails, CountDownLatch countDownLatch) {
        try {
            log.info("start executeAsync");
            this.saveBatch(SysUserAuthdetails);
            log.info("end executeAsync");
        } finally {
            countDownLatch.countDown();
        }
    }

    public List<SysUserAuthdetail> buildSysUserAuthDetails(List<SysUser> users, String roleId) {
        List<SysUserAuthdetail> sysUserAuthDetails = new ArrayList<>();
        Map<String, List<SysMenuRoleDto>> menusAndPointsMap = getMenusAndPointsByRoleId(roleId);
        List<SysMenuRoleDto> menuList = menusAndPointsMap.get("menuList");
        List<SysMenuRoleDto> pointList = menusAndPointsMap.get("pointList");
        users.forEach(user -> {
            sysUserAuthDetails.addAll(getSysUserAuthdetailByMenu(user, menuList, "0"));
            sysUserAuthDetails.addAll(getSysUserAuthdetailByMenu(user, pointList, "1"));
        });
        return sysUserAuthDetails;
    }

    public Map<String, List<SysMenuRoleDto>> getMenusAndPointsByRoleId(String roleId) {
        SysRole sysRole = sysRoleMapper.selectById(roleId);
        List<SysModule> sysModules = sysModuleService.getSysModulesByRoleId(roleId);
        Map<String, SysModule> moduleMap = sysModules.stream().collect(Collectors.toMap(SysModule::getId, v -> v, (k1, k2) -> k1));
        Map<String, List<SysMenuRoleDto>> resultMap = new HashMap<>();
        // 通过roleId 获取菜单详细信息
        List<SysMenu> sysMenus = sysMenuService.getSysMenusByRoleId(roleId);
        List<SysMenuRoleDto> menuList = sysMenus.stream().filter(item -> moduleMap.containsKey(item.getModuleId())).map(sysMenu -> {
            SysMenuRoleDto sysMenuRoleDto = new SysMenuRoleDto();
            BeanUtil.copyProperties(sysMenu, sysMenuRoleDto);
            sysMenuRoleDto.setModuleName(moduleMap.get(sysMenu.getModuleId()).getName());
            sysMenuRoleDto.setModuleCode(moduleMap.get(sysMenu.getModuleId()).getCode());
            sysMenuRoleDto.setRoleId(sysRole.getId());
            sysMenuRoleDto.setRoleName(sysRole.getRoleName());
            sysMenuRoleDto.setRoleCode(sysRole.getCode());
            return sysMenuRoleDto;
        }).collect(Collectors.toList());
        resultMap.put("menuList", menuList);
        List<SysPoints> sysPoints = sysPointsService.getSysPointsByRoleId(roleId);
        // 通过roleId 获取功能详细信息
        List<SysMenuRoleDto> pointsList = sysPoints.stream().filter(item -> moduleMap.containsKey(item.getModuleId())).map(sysPoint -> {
            SysMenuRoleDto sysMenuRoleDto = new SysMenuRoleDto();
            BeanUtil.copyProperties(sysPoint, sysMenuRoleDto);
            sysMenuRoleDto.setModuleName(moduleMap.get(sysPoint.getModuleId()).getName());
            sysMenuRoleDto.setModuleCode(moduleMap.get(sysPoint.getModuleId()).getCode());
            sysMenuRoleDto.setRoleId(sysRole.getId());
            sysMenuRoleDto.setRoleName(sysRole.getRoleName());
            sysMenuRoleDto.setRoleCode(sysRole.getCode());
            return sysMenuRoleDto;
        }).collect(Collectors.toList());
        resultMap.put("pointList", pointsList);
        return resultMap;
    }
}
